import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.file.*;
import java.util.*;

public class TCP
{
	static Socket socket;
	static DataInputStream in;
	static DataOutputStream out;
	
	//values to remember after SSL exchange
	static int sessionId;
	static Message.Ciphers cipher;
	static byte[] s;
	static byte[] k;
	
	public static void SendMessage(Message m) throws Exception
	{
		byte[] mb = m.ToBytes();
		out.write(mb, 0, mb.length);
	}
	
	public static Message ReceiveMessage() throws Exception
	{
		byte[] buffer = new byte[4000];
		int r = in.read(buffer);
		byte[] mb = Arrays.copyOfRange(buffer, 0, r);
		return new Message(mb);
	}
	
	public static int getRandom(){
        Random random = new Random();
        int temp = random.nextInt(1750000);
        return temp;
    }
	
	public static byte[] GenerateK(byte[] s, byte[] aliceR, byte[] bobR) throws Exception
	{
		byte[] k = new byte[s.length + aliceR.length + bobR.length];
		System.arraycopy(s, 0, k, 0, s.length);
		System.arraycopy(aliceR, 0, k, s.length, aliceR.length);	
		System.arraycopy(bobR, 0, k, s.length + aliceR.length, bobR.length);	
		return Utils.Hash(k);
	}
	
	public static byte[] IntToByte(int i)
	{
		return ByteBuffer.allocate(4).putInt(i).array();
	}
	
	public static void PrintToConsole(boolean send, Message m)
	{
		//System.out.println("---------------------");
		System.out.println();
		if (send) System.out.println("Sent:");
		else System.out.println("Received:");
		System.out.println(m.toString());
		//System.out.println("---------------------");
		System.out.println();
	}
	
	public static Message SimulateAttacker(Message m) throws Exception
	{
		System.out.println();
		System.out.print("Should an attacker modify " + m.type + " message? (y/n): ");
		String opt = Utils.GetUserInput("");
		
		if (opt.toLowerCase().equals("y"))
		{
			if (m.type == Message.MessageType.SessionStartRequest) 
			{
				m.r = Arrays.copyOfRange(Utils.Hash(m.r), 0, 4);
				System.out.println("R has been modifed");	
			}
			else if(m.type == Message.MessageType.SessionStartResponce) 
			{
				System.out.println("Which part of the message should be modified?:");
				System.out.println("1. sessionId");
				System.out.println("2. certificate");
				System.out.println("3. cipher selection");
				System.out.println("4. R");
				String s = Utils.GetUserInput("Enter selection: ");
				
				if (s.equals("1"))
				{
					m.sessionId = 0;
					System.out.println("SessionId has been modifed");	
				}
				else if (s.equals("2"))
				{
					m.e = Arrays.copyOfRange(Utils.Hash(m.r), 0, 4);
					System.out.println("Certificate has been modifed");	
				}
				else if (s.equals("3"))
				{
					if (m.cipher == Message.Ciphers.RC4) m.cipher = Message.Ciphers.CFB;
					else if (m.cipher == Message.Ciphers.CFB) m.cipher = Message.Ciphers.CBC;
					else if (m.cipher == Message.Ciphers.CBC) m.cipher = Message.Ciphers.PCBC;
					else m.cipher = Message.Ciphers.RC4;
					System.out.println("Cipher selection has been modifed");				
				}
				else if (s.equals("4"))
				{
					m.r = Arrays.copyOfRange(Utils.Hash(m.r), 0, 4);
					System.out.println("R has been modifed");	
				}
			}
			else if(m.type == Message.MessageType.SessionResumeRequest) 
			{
				System.out.println("Which part of the message should be modified?:");
				System.out.println("1. sessionId");
				System.out.println("2. R");
				String s = Utils.GetUserInput("Enter selection: ");
				
				if (s.equals("1"))
				{
					m.sessionId = 0;
					System.out.println("SessionId has been modifed");	
				}
				else if (s.equals("2"))
				{
					m.r = Arrays.copyOfRange(Utils.Hash(m.r), 0, 4);
					System.out.println("R has been modifed");	
				}
			}
			else if(m.type == Message.MessageType.SessionResumeResponce) 
			{
				System.out.println("Which part of the message should be modified?:");
				System.out.println("1. sessionId");
				System.out.println("2. Hash of Msgs");
				System.out.println("3. cipher selection");
				System.out.println("4. R");
				String s = Utils.GetUserInput("Enter selection: ");
				
				if (s.equals("1"))
				{
					m.sessionId = 0;
					System.out.println("SessionId has been modifed");	
				}
				else if (s.equals("2"))
				{
					m.hashOfMsgs = Utils.Hash(m.hashOfMsgs);
					System.out.println("Hash of Msgs has been modifed");	
				}
				else if (s.equals("3"))
				{
					if (m.cipher == Message.Ciphers.RC4) m.cipher = Message.Ciphers.CFB;
					else if (m.cipher == Message.Ciphers.CFB) m.cipher = Message.Ciphers.CBC;
					else if (m.cipher == Message.Ciphers.CBC) m.cipher = Message.Ciphers.PCBC;
					else m.cipher = Message.Ciphers.RC4;
					System.out.println("Cipher selection has been modifed");				
				}
				else if (s.equals("4"))
				{
					m.r = Arrays.copyOfRange(Utils.Hash(m.r), 0, 4);
					System.out.println("R has been modifed");	
				}
			}
			else if(m.type == Message.MessageType.KeyedHashOfMsgs) 
			{
				m.hashOfMsgs = Utils.Hash(m.hashOfMsgs);
				System.out.println("hash of Msgs has been modifed");	
			}
			else if(m.type == Message.MessageType.PreMasterSecret) 
			{
				System.out.println("Which part of the message should be modified?:");
				System.out.println("1. S");
				System.out.println("2. Hash of Msgs");
				String s = Utils.GetUserInput("Enter selection: ");
				
				if (s.equals("1"))
				{
					m.s = Arrays.copyOfRange(Utils.Hash(m.s), 0, 4);
					System.out.println("S has been modifed");	
				}
				else if (s.equals("2"))
				{
					m.hashOfMsgs = Utils.Hash(m.hashOfMsgs);
					System.out.println("Hash of Msgs has been modifed");
				}
			}
			else if(m.type == Message.MessageType.FileReceive || m.type == Message.MessageType.FileSend) 
			{
				byte[] h = Utils.Hash(m.data);
				
				int copyLength = 8;
				if (m.data.length < 8)
					copyLength = m.data.length;
					
				System.arraycopy(h, 0, m.data, 0, copyLength);
				System.out.println("Data has been modifed");
			}
		}
		
		return m;
	}
}